"""
@Author  : 康帅
@Time    : 2021/4/15 10:45
@Function: 线程锁实现同步控制:同步指的是协同配合而不是一起执行的动作
"""

import threading
import random

# 案例一:
# def run1():
#     """
#     输出:
#         这样运行的结果是无序没法控制的，但是当你加上一把锁后，就不一样了
#     """
#     while 1:
#         print('我是老大，我先运行')
#
#
# def run2():
#     while 1:
#         print('我是老二，我第二运行')
#
#
# def run3():
#     while 1:
#         print('我是老三，我最后运行')
#
#
# t1 = threading.Thread(target=run1)
# t2 = threading.Thread(target=run2)
# t3 = threading.Thread(target=run3)
# t1.start()
# t2.start()
# t3.start()

"""
acquire():上锁，这个时候只能运行上锁后的代码
release():解锁，解锁后把资源让出来，给其他线程使用
"""

# 案例二:
# def run4():
#     while 1:
#         if l1.acquire():
#             # 如果第一把锁上锁了
#             print('我是老大，我先运行')
#             l2.release()
#             # 释放第二把锁
#
#
# def run5():
#     while 1:
#         if l2.acquire():
#             # 如果第二把锁上锁了
#             print('我是老二，我第二运行')
#             l3.release()
#             # 释放第三把锁
#
#
# def run6():
#     while 1:
#         if l3.acquire():
#             # 如果第三把锁上锁了
#             print('我是老三，我最后运行')
#             l1.release()
#             # 释放第一把锁
#
#
# t1 = threading.Thread(target=run4)
# t2 = threading.Thread(target=run5)
# t3 = threading.Thread(target=run6)
#
# l1 = threading.Lock()
# l2 = threading.Lock()
# l3 = threading.Lock()
# # 实例化三把锁
#
# l2.acquire()
# l3.acquire()
#
# t1.start()
# t2.start()
# t3.start()

"""
lock还有Rlock的方法，RLock允许在同一线程中被多次acquire（比如你一个函数上了锁，这个函数调用另一个函数，另一个函数也上了锁 ）。
而Lock却不允许这种情况。否则会出现死循环，程序不知道解哪一把锁。注意：如果使用RLock，那么acquire和release必须成对出现，
即调用了n次acquire，必须调用n次的release才能真正释放所占用的锁。
"""


def produce():
    global q
    while 1:
        con.acquire()
        # 必须在有锁的前提下才能使用条件变量
        q = str(random.randint(1, 100))
        print('我生成了一个随机数字:' + q)
        con.notify()
        # 发起一个信号，释放一个被堵塞的线程
        con.wait()
        # 发起一个信号，堵塞当前线程，等待另一个notify出现的时候就执行下面的代码
        con.release()
        # 必须要解锁


def consume():
    global q
    while 1:
        con.acquire()
        # 必须在有锁的前提下才能使用条件变量
        print('我获取到你生成的随机数字:' + q)
        con.notify()
        # 发起一个信号，释放一个被堵塞的线程
        con.wait()
        # 堵塞当前线程
        con.release()


t1 = threading.Thread(target=produce)
t2 = threading.Thread(target=consume)
con = threading.Condition()
t1.start()
t2.start()
